package com.gitee.feizns.dynamic.reflect;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * <b>常用数据类型工具类</b>
 *
 * @author feizns
 * @since 2019/5/29
 */
public abstract class Types {

    //=============================基础数据类型和包装类型之间的映射关系===============================
    private static final Map<Class<?>, Class<?>> PRIMITIVE_MAPPING_WRAPPER = new HashMap<>();

    static {
        PRIMITIVE_MAPPING_WRAPPER.put(byte.class, Byte.class);
        PRIMITIVE_MAPPING_WRAPPER.put(short.class, Short.class);
        PRIMITIVE_MAPPING_WRAPPER.put(int.class, Integer.class);
        PRIMITIVE_MAPPING_WRAPPER.put(long.class, Long.class);
        PRIMITIVE_MAPPING_WRAPPER.put(float.class, Float.class);
        PRIMITIVE_MAPPING_WRAPPER.put(double.class, Double.class);
        PRIMITIVE_MAPPING_WRAPPER.put(boolean.class, Boolean.class);
        PRIMITIVE_MAPPING_WRAPPER.put(char.class, Character.class);
    }
    //=============================基础数据类型和包装类型之间的映射关系===============================

    /**
     * <b>获取对应基础类型的包装类型</b>
     * <p>
     *     如果参数primitive是基础类型，则返回对应的包装类型
     * </p>
     * <pre>{@code
     *      System.out.println(boolean.class == Boolean.class);             //false
     *      System.out.println(getWrapper(boolean.class) == Boolean.class); //true
     * }</pre>
     * @param primitive 基础类型类
     * @return 如果参数是基础类型的Class对象则返回对应的包装类型Class对象
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> ofWrapper(Class<T> primitive) {
        Class<T> wrapper = (Class<T>) PRIMITIVE_MAPPING_WRAPPER.get(primitive);
        return wrapper != null ? wrapper : primitive;
    }

    /**
     * <b>是否是基础数据类型或是String（非javabean）</b>
     * <p>（该判断主要判断是否是jdk类库自己的类型）</p>
     * @param type {@link Class}
     * @return 返回是否是基础数据类型或是String
     */
    public static boolean isPrimitive(Class<?> type) {
        if ( !type.isPrimitive() ) {
            return Optional.ofNullable(type.getPackage())
                    .map(Package::getName)
                    .map(name -> name.startsWith("java"))
                    .orElse(Boolean.FALSE);
        }
        return true;
    }

    /**
     * <b>是否是一个javabean</b>
     * <b>该判断主要判断是否是jdk类库自己的类型,如果是否则代表是自定义的javabean</b>
     * @param type {@link Class}
     * @return 返回是否是javabean
     */
    public static boolean isJavaBeanType(Class<?> type) {
        return !isPrimitive(type);
    }

    /**
     * <b>是否是字符串类型</b>
     * @param type 类型
     * @return 是字符串返回true，反之返回false
     */
    public static boolean isCharSequence(Class<?> type) {
        return CharSequence.class.isAssignableFrom(type);
    }

    /**
     * <b>是否是字符串类型</b>
     * @param type 类型
     * @return 是字符串返回true，反之返回false
     */
    public static boolean isString(Class<?> type) {
        return String.class == type;
    }

    /**
     * 是否是一个数字类型
     * @param type 类型Class对象
     * @return 返回是否是一个数字类型
     */
    public static boolean isNumber(Class<?> type) {
        return Number.class.isAssignableFrom(ofWrapper(type));
    }

}
